package model.factories;

import java.util.Map;
import java.util.Scanner;
import java.util.regex.Pattern;
import model.Interpreter;
import model.SyntaxErrorException;
import model.commands.Command;


/**
 * A factory used to build Command objects.
 * 
 * @author Erick Gonzalez
 * @author JLongley
 */
public abstract class CommandFactory {
    private Interpreter myInterpreter;

    /**
     * 
     * @param interpreter the interpreter that owns this commandFactory
     */
    public CommandFactory(Interpreter interpreter) {
        myInterpreter = interpreter;
    }

    protected Interpreter getInterpreter() {
        return myInterpreter;
    }

    /**
     * Creates a command of a given type and assigns its child arguments when
     * the number of arguments is known.
     * For example for ADD 1 1, create an ADD command with two children,
     * literalNodes 1 and 1.
     * 
     * @param commandReader the input stream
     * @param c the type of command to create
     * @param numArgs the number of child nodes to assign to this command
     * @return a new command node with children
     * @throws SyntaxErrorException this catch-all will work for any unknown
     *         token.
     *         It will catch unknown functions and variables as well as an
     *         incorrect number of arguments
     */
    protected Command createKnownArgsCommand(Scanner commandReader,
                                             Command c,
                                             int numArgs,
                                             Map<String, Integer> variables) throws 
                                             SyntaxErrorException {
        // remove command keyword from commandReader
        commandReader.next();

        for (int i = 0; i < numArgs; ++i) {            
            Command arg = myInterpreter.parse(commandReader, variables);
            c.getArguments().add(arg);
        }        
        return c;
    }
    
    /**
     * 
     * @param commandReader a command reader
     * @param variables a mapping from variable name to variable value
     * @return a Command object
     * @throws SyntaxErrorException this catch-all will work for any unknown
     *         token.
     *         It will catch unknown functions and variables as well as an
     *         incorrect number of arguments
     */
    public abstract 
    Command createCommand(Scanner commandReader, 
                          Map<String, Integer> variables) throws SyntaxErrorException;
    
    /**
     * 
     * @return a pattern that matches valid keywords for this command
     */
    public abstract Pattern patternToMatch();
}
